from django.http import HttpResponse, JsonResponse
from django.views.decorators.csrf import csrf_exempt
from rest_framework.parsers import JSONParser
from rest_framework import generics
from drf_test.snippets.models import Snippets
from drf_test.snippets import SnippetSerilizer, UserSerializer
from django.contrib.auth.models import User
from  rest_framework import permissions
from drf_test.snippets import IsOwnerOrReadOnly


@csrf_exempt
def snippet_list(request):
    """List all code  snippets, or create a new snippet"""
    if request.method == 'GET':
        snippets = Snippets.objects.all()
        serilizer = SnippetSerilizer(snippets, many=True)
        return JsonResponse(serilizer.data, safe=False)

    elif request.method == 'POST':
        data = JSONParser().parse(request)
        serializer = SnippetSerilizer(data=data)
        if serializer.is_valid():
            serializer.save()
            return JsonResponse(serializer.data, status=201)
        return JsonResponse(serializer.errors, status=400)


@csrf_exempt
def snippet_detail(request, pk):
    """retrieve, update or delete a code snippet"""
    try:
        snippet = Snippets.objects.get(pk=pk)
    except Snippets.DoesNotExist:
        return HttpResponse(status=404)

    if request.method == "GET":
        serilizer = SnippetSerilizer(snippet)
        return JsonResponse(serilizer.data)

    elif request.method == "PUT":
        data = JSONParser().parse(request)
        serializer = SnippetSerilizer(snippet, data=data)
        if serializer.is_valid():
            serializer.save()
            return JsonResponse(serializer.data)
        return JsonResponse(serializer.errors, status=400)

    elif request.method == "DELETE":
        snippet.delete()
        return JsonResponse(status=204)

# 包装API视图
"""
REST框架提供了两个包装器， 可用于编写API视图
    1、该@api_view装饰与基本的功能是鄂图工作
    2、该APIView类是基于类的视图工作
    这些包装器提供了乙烯额功能， 列入确保你Request再视图中接受的实例，并向Response对象添加上下文，以便可以执行内容的协商。
    包装器还提供乙烯额行为， 列入405 method not allowed再适当的时候返回响应，以及处理使用格式错误的输入进行ParserError访问时
发生的任何异常requestd.data


@api_view(["GET", "POST"])
def snippet_list(request, format=None):
    "List all code snippets or create a new snippet"
    if request.method == "GET":
        snippets = Snippets.objects.all()
        serializer = SnippetSerilizer(snippets, many=True)
        return Response(serializer.data)

    elif request.method == "POST":
        serializer = SnippetSerilizer(data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data, status=status.HTTP_201_CREATED)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)


@api_view(["GET", "PUT", "DELETE"])
def snippet_detail(request, pk, format=None):
    "Retrieve, update or delete a code  snippet"
    try:
        snippet = Snippets.objects.get(pk=pk)
    except Snippets.DoesNotExist:
        return Response(status=status.HTTP_404_NOT_FOUND)
    if request.method == "GET":
        serializer = SnippetSerilizer(snippet)
        return Response(serializer.data, status=status.HTTP_200_OK)

    elif request.method == "PUT":
        serializer = SnippetSerilizer(snippet, data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data, status=status.HTTP_200_OK)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

    elif request.method == "DELETE":
        snippet.delete()
        return Response(status=status.HTTP_200_OK)
"""

# 3基于类的视图
"""
我们还可以使用基于类的视图而不是基于函数的视图来编写API视图。正如我们将看到的那样， 这是一个强大的模式，它允许我们重用
常见的功能， 并帮助我们的代码dry。

我们将从将视图重写为基于类的视图开始， 所以我们重构views.py


class SnippetList(APIView):
    "List all snippets, or create a  new snippet"
    def get(self, request, format=None):
        snippets = Snippets.objects.all()
        serializer = SnippetSerilizer(snippets, many=True)
        return Response(serializer.data, status=status.HTTP_200_OK)

    def post(self, request, format=None):
        serializer = SnippetSerilizer(data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data, status=status.HTTP_200_OK)
        return Response(status=status.HTTP_400_BAD_REQUEST)


class SnippetDetail(APIView):
    "Retrieve, update oer dalete a snippet instance"
    def get_object(self, pk):
        try:
            snippet = Snippets.objects.get(pk=pk)
            return snippet
        except Snippets.DoesNotExist:
            raise status.HTTP_404_NOT_FOUND

    def get(self, request, pk, format=None):
        snippet = self.get_object(pk)
        serializer = SnippetSerilizer(snippet)
        return Response(serializer.data, status=status.HTTP_200_OK)

    def put(self, request, pk, format=None):
        snippet = self.get_object(pk)
        serializer = SnippetSerilizer(snippet, request.data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data, status=status.HTTP_200_OK)
        return Response(status=status.HTTP_400_BAD_REQUEST)

    def delete(self, request, pk, format=None):
        snippet = self.get_object(pk)
        snippet.delete()
        return Response(status=status.HTTP_204_NO_CONTENT)
"""

# 4 使用minxins
"""
    使用基于类的视图的最大胜利之一就是它使我们能够轻松的组合可重用的行为。
    到目前为止， 对于我们创建的任何模型支持的API视图， 我们一直使用的create/retrieve/update/delete操作非常相似。这些常见的行为
再REST框架的minxin类中实现.


class SnippetList(mixins.ListModelMixin,
                  mixins.CreateModelMixin,
                  generics.GenericAPIView):
    queryset = Snippets.objects.all()
    serializer_class = SnippetSerilizer

    def get(self, request, *args, **kwargs):
        return self.list(request, *args, **kwargs)

    def post(self, request, *args, **kwargs):
        return self.create(request, *args, **kwargs)


class SnippetDetail(mixins.RetrieveModelMixin,
                    mixins.UpdateModelMixin,
                    mixins.DestroyModelMixin,
                    generics.GenericAPIView):
    queryset = Snippets.objects.all()
    serializer_class = SnippetSerilizer

    def get(self, request, *args, **kwargs):
        return self.retrieve(request, *args, **kwargs)

    def put(self, request, *args, **kwargs):
        return self.update(request, *args, **kwargs)

    def delete(self, request, *args, **kwargs):
        return self.destroy(request, *args, **kwargs)
"""


# 5 基于通用类的视图
"""
    使用mixins类， 我们重写了视图， 以使用更少的代码，但是我们可以更进一步。REST框架提供了一组已经混入的通用视图。
我们可以使用它们来进一步缩减views.py模块的数量
"""


class SnippetList(generics.ListCreateAPIView):
    queryset = Snippets.objects.all()
    serializer_class = SnippetSerilizer
    permissions_class = [permissions.IsAuthenticatedOrReadOnly,
                         IsOwnerOrReadOnly]

    def perform_create(self, serializer):
        serializer.save(owner=self.request.user)


class SnippetDetail(generics.RetrieveUpdateDestroyAPIView):
    queryset = Snippets.objects.all()
    serializer_class = SnippetSerilizer
    permissions_class = [permissions.IsAuthenticatedOrReadOnly,
                         IsOwnerOrReadOnly]


class UserList(generics.ListAPIView):
    queryset = User.objects.all()
    serializer_class = UserSerializer


class UserDetail(generics.RetrieveAPIView):
    queryset = User.objects.all()
    serializer_class =  UserSerializer

















